home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / AMScen_0_9.lha / AMScen / mail.m < prev    next >
Text File  |  1995-01-21  |  24KB  |  840 lines

  1. /*
  2.  * Amiga MUD
  3.  *
  4.  * Copyright (c) 1995 by Chris Gray
  5.  */
  6.  
  7. /*
  8.  * mail.m - code to handle the mail system and the postman.
  9.  *    NOTE: rooms referenced directly:
  10.  *        r_mailRoom - several things
  11.  *        r_garbageRoom - home for letters
  12.  *        r_neEnd, r_esEnd, r_swEnd, r_wnEnd - mailboxes
  13.  *        r_mallEntrance - so Postman erases the recorder
  14.  *    NOTE: other direct references: recorderErase, o_recorder,
  15.  *        p_oReadString, p_rRegisterAction (both in verbs.m)
  16.  *    NOTE: because the mailroom is actually setup here, this file needs
  17.  *        to be sourced by the same player who owns the mailroom, or
  18.  *        the mailroom needs to be public. Normally, this file is
  19.  *        sourced by SysAdmin.
  20.  *    NOTE: we assume that all mailboxes are in lighted rooms, and that
  21.  *        the mailroom is lighted.
  22.  *    NOTE: MAX_CARRY is ignored for letters. This includes writing them,
  23.  *        the initial REGISTER and picking up new mail.
  24.  */
  25.  
  26. /*****************************************************************************\
  27. *                                          *
  28. *    This stuff here sets up the mail facility                  *
  29. *                                          *
  30. \*****************************************************************************/
  31.  
  32. use t_streets
  33.  
  34. private tp_mail CreateTable().
  35. use tp_mail
  36.  
  37. define tp_mail MAX_BULLETINS 20.
  38.  
  39. define tp_mail p_pMailRegistered CreateBoolProp().
  40. define tp_mail p_pLetterTarget CreateThingProp().   /* also put on letters */
  41. define tp_mail p_oLetterSender CreateThingProp().   /* so can change name */
  42. define tp_mail p_oLettersHere CreateThingListProp()./* on boxes & mailRoom */
  43. define tp_mail p_oPostManRoute CreateStringProp().  /* codes for moves */
  44. define tp_mail p_oPostManIndex CreateIntProp().     /* index into the string */
  45. define tp_mail p_oPostManClearing CreateBoolProp(). /* used to idle him */
  46. define tp_mail p_oPostManCleared CreateBoolProp().  /* ditto */
  47. define tp_mail p_rNewLetter CreateBoolProp().        /* flag mailroom for new */
  48. define tp_mail p_oPostManDelay CreateIntProp().     /* delay before move */
  49. define tp_mail p_oBulletinDate CreateStringProp().
  50. define tp_mail p_oBulletinNumber CreateIntProp().
  51.  
  52. define tp_mail o_letter CreateThing(nil).
  53. o_letter@p_oHome := r_garbageRoom.
  54.  
  55. define tp_mail o_bulletin CreateThing(nil).
  56. o_bulletin@p_oHome := r_garbageRoom.
  57.  
  58. r_mailRoom@p_oLettersHere := CreateThingList().
  59. r_mailRoom@p_rNewLetter := false.
  60.  
  61. define tp_mail proc mailboxGet(thing th)status:
  62.  
  63.     Print("The mailbox is firmly bolted down.\n");
  64.     OPrint(Me()@p_pName + " tries to rip up the mailbox.\n");
  65.     fail
  66. corp;
  67.  
  68. define tp_mail o_mailbox CreateThing(nil).
  69. SetThingStatus(o_mailbox, ts_readonly).
  70. o_mailbox@p_oName := "mailbox;official.box;mail,official".
  71. o_mailbox@p_oDesc :=
  72.     "The mailbox is bright red, with a slot in the top used for posting "
  73.     "letters. It is locked up tight - only an official representative "
  74.     "of the postal service can get things out of it.".
  75. o_mailbox@p_oGetChecker := mailboxGet.
  76.  
  77. define tp_mail proc boardGet(thing th)status:
  78.  
  79.     Print("The bulletin board is firmly attached.\n");
  80.     OPrint(Me()@p_pName + " tries to rip off the bulletin board.\n");
  81.     fail
  82. corp;
  83.  
  84. define tp_mail proc boardRead()void:
  85.     thing board, bulletin;
  86.     list thing lt;
  87.     string what, what2;
  88.     int count, i, n;
  89.  
  90.     board := It();
  91.     lt := board@p_oContents;
  92.     count := Count(lt);
  93.     what := GetWord();
  94.     what2 := GetWord();
  95.     if what = "" or what == "bulletins" or what == "contents" or
  96.     what == "notices" or what == "board" or
  97.     what == "bulletin" and what2 == "board"
  98.     then
  99.     if count = 0 then
  100.         Print("There are no bulletins posted yet.\n");
  101.     else
  102.         Print("Current bulletins (number, date posted, author):\n");
  103.         for i from 0 upto count - 1 do
  104.         bulletin := lt[i];
  105.         Print("  " + IntToString(bulletin@p_oBulletinNumber) + "  " +
  106.             bulletin@p_oBulletinDate + "  " +
  107.             bulletin@p_oCreator@p_pName + "\n");
  108.         od;
  109.     fi;
  110.     else
  111.     if what == "bulletin" or what == "notice" then
  112.         what := what2;
  113.     fi;
  114.     if SubString(what, 0, 1) = "#" then
  115.         what := SubString(what, 1, Length(what) - 1);
  116.     fi;
  117.     if what = "" then
  118.         Print("You must say which bulletin you want to read.\n");
  119.     else
  120.         n := StringToPosInt(what);
  121.         if n < 0 then
  122.         Print("\"" + what + "\" is not a valid bulletin number.\n");
  123.         else
  124.         i := 0;
  125.         while i < count and lt[i]@p_oBulletinNumber ~= n do
  126.             i := i + 1;
  127.         od;
  128.         if i = count then
  129.             Print("There is no bulletin " + what + " on the board.\n");
  130.         else
  131.             Print(lt[i]@p_oReadString + "\n");
  132.         fi;
  133.         fi;
  134.     fi;
  135.     fi;
  136. corp;
  137.  
  138. define tp_mail proc actualPostBulletin(thing bulletin, board)void:
  139.     thing me, oldNote;
  140.     list thing lt;
  141.     int n;
  142.  
  143.     me := Me();
  144.     lt := board@p_oContents;
  145.     bulletin@p_oBulletinDate := Date();
  146.     n := board@p_oBulletinNumber;
  147.     board@p_oBulletinNumber := n + 1;
  148.     bulletin@p_oBulletinNumber := n;
  149.     bulletin@p_oName := IntToString(n) + ";bulletin";
  150.     if Count(lt) >= 20 then
  151.     oldNote := lt[0];
  152.     ClearThing(oldNote);
  153.     DelElement(lt, oldNote);
  154.     fi;
  155.     AddTail(lt, bulletin);
  156.     bulletin -- p_oCarryer;
  157.     bulletin@p_oWhere := board;
  158.     bulletin@p_oInvisible := true;
  159.     DelElement(me@p_pCarrying, bulletin);
  160.     Print("Bulletin posted.\n");
  161.     if not me@p_pHidden then
  162.     OPrint(FormatName(me@p_pName) + " posts a bulletin.\n");
  163.     else
  164.     OPrint("A new bulletin has been posted.\n");
  165.     fi;
  166. corp;
  167.  
  168. define tp_mail proc boardPutIn(thing bulletin, board)status:
  169.  
  170.     if Parent(bulletin) = o_bulletin then
  171.     actualPostBulletin(bulletin, board);
  172.     succeed
  173.     else
  174.     Print("You can't post that on the bulletin board.\n");
  175.     fail
  176.     fi
  177. corp;
  178.  
  179. define tp_mail proc boardTakeFrom(thing bulletin, board)status:
  180.     thing me;
  181.  
  182.     me := Me();
  183.     if bulletin@p_oCreator = me or MeCharacter() = SysAdmin then
  184.     AddTail(me@p_pCarrying, bulletin);
  185.     DelElement(board@p_oContents, bulletin);
  186.     bulletin -- p_oWhere;
  187.     bulletin@p_oCarryer := me;
  188.     Print("You take " + FormatName(bulletin@p_oName) +
  189.         " from the bulletin board.\n");
  190.     if not me@p_pHidden then
  191.     OPrint(me@p_pName +
  192.         " takes a bulletin from the bulletin board.\n");
  193.     else
  194.         OPrint("A bulletin has been removed from the bulletin board.\n");
  195.     fi;
  196.     bulletin@p_oName := "bulletin";
  197.     bulletin -- p_oInvisible;
  198.     succeed
  199.     else
  200.     Print("That's not your bulletin.\n");
  201.     fail
  202.     fi
  203. corp;
  204.  
  205. define tp_mail o_bulletinBoard CreateThing(nil).
  206. SetThingStatus(o_bulletinBoard, ts_readonly).
  207. o_bulletinBoard@p_oName := "board;bulletin".
  208. o_bulletinBoard@p_oDesc :=
  209.     "The bulletin board is a framed corkboard which is used for the posting "
  210.     "of public notices. Anyone can post on it, and anyone can read what is "
  211.     "posted on it. Use 'read notices' to see what notices exist. Use "
  212.     "'read N', where N is the number of a bulletin, to read that bulletin. "
  213.     "Use 'take bulletin N from board' to take a bulletin from the board.".
  214. o_bulletinBoard@p_oGetChecker := boardGet.
  215. o_bulletinBoard@p_oActWord := "read".
  216. o_bulletinBoard@p_oActAction := boardRead.
  217. o_bulletinBoard@p_oPutInMeChecker := boardPutIn.
  218. o_bulletinBoard@p_oTakeFromMeChecker := boardTakeFrom.
  219.  
  220. define tp_mail o_postalService CreateThing(nil).
  221. o_postalService@p_pName := "the postal service".
  222.  
  223. define tp_mail proc mailRoomRegister()bool:
  224.     thing me, th;
  225.     string name;
  226.     list thing lt;
  227.  
  228.     me := Me();
  229.     name := FormatName(me@p_pName);
  230.     if me@p_pMailRegistered then
  231.     Print("Only one registration per customer, sir!\n");
  232.     if not me@p_pHidden then
  233.         OPrint(name + " walks up to the counter, but is turned away.\n");
  234.     fi;
  235.     false
  236.     else
  237.     lt := me@p_pCarrying;
  238.     th := CreateThing(o_letter);
  239.     SetThingStatus(th, ts_public);
  240.     GiveThing(th, SysAdmin);
  241.     AddTail(lt, th);
  242.     th@p_oName := "service;letter,from,the,postal.letter";
  243.     th@p_oHome := r_garbageRoom;
  244.     th@p_oReadString := "Date: " + Date() +
  245. "\nFrom: the postal service\n\n    Welcome to the mail system. You can use "
  246. "any of the mailboxes scattered around to mail letters to people, but you "
  247. "must go to the mail room to pick up new letters from others to you.\n";
  248.     th@p_pLetterTarget := me;
  249.     th@p_oLetterSender := o_postalService;
  250.     th@p_oCarryer := me;
  251.     th@p_oCreator := me;
  252.     me@p_pMailRegistered := true;
  253.     Print(
  254. "You walk up to the counter to register. A clerk comes up to the wicket and "
  255. "helps you fill out all of the forms in triplicate. He then gives you a "
  256. "letter, says goodbye, and leaves.\n");
  257.     if not me@p_pHidden then
  258.         OPrint(name +
  259.         " walks up to the counter and is given something.\n");
  260.     else
  261.         OPrint("The clerk at the counter hads something to thin air.\n");
  262.     fi;
  263.     true
  264.     fi
  265. corp;
  266. r_mailRoom@p_rRegisterAction := mailRoomRegister.
  267.  
  268. define tp_mail r_postmanHidden CreateThing(nil).
  269.  
  270. define tp_mail proc postmanStep()void:
  271.     list thing ltMan, ltHere;
  272.     thing here, me, mailbox, letter;
  273.     string route;
  274.     int index, count;
  275.     status st;
  276.     bool idling;
  277.  
  278.     me := Me();
  279.     here := Here();
  280.     idling := false;
  281.     if ClientsActive() then
  282.     /* someone is playing */
  283.     me@p_oPostManClearing := false;
  284.     me@p_oPostManCleared := false;
  285.     else
  286.     /* no active players, and we have collected all mail - go idle */
  287.     if me@p_oPostManCleared then
  288.         idling := true;
  289.     fi;
  290.     fi;
  291.     if idling then
  292.     After(60, postmanStep);
  293.     elif here = r_postmanHidden then
  294.     SetLocation(r_mailRoom);
  295.     OPrint("Postman comes out from the private areas of the mailroom.\n");
  296.     me@p_oPostManRoute := "";
  297.     me@p_oPostManIndex := 0;
  298.     if r_mailRoom@p_rNewLetter then
  299.         /* make sure we deliver that last letter */
  300.         r_mailRoom@p_rNewLetter := false;
  301.         me@p_oPostManClearing := false;
  302.         me@p_oPostManCleared := false;
  303.     fi;
  304.     SetLocation(r_mailRoom);
  305.     ForEachAgent(r_mailRoom, ShowIconOnce);
  306.     After(20, postmanStep);
  307.     else
  308.     route := me@p_oPostManRoute;
  309.     index := me@p_oPostManIndex;
  310.     if index = Length(route) then
  311.         st := FindName(here@p_rContents, p_oName, "mailbox");
  312.         if st = fail then
  313.         Say("", "AAAAAARRRRRRGGGGGHHHHH! I'm lost!!!!");
  314.         Log("Postman is lost! Route = '" + route + "', index = " +
  315.             IntToString(index) + ", " + here@p_rName + "\n");
  316.         else
  317.         /* collect the mail from this mailbox, and get new route */
  318.         mailbox := FindResult();
  319.         ltHere := mailbox@p_oLettersHere;
  320.         if ltHere = nil then
  321.             Say("", "AAAAARRRRGGGGGHHHH! Fake mailbox!");
  322.         else
  323.             ltMan := me@p_oLettersHere;
  324.             count := Count(ltHere);
  325.             if count = 0 then
  326.             OPrint("Postman looks, but there is no mail in the "
  327.                 "mailbox.\n");
  328.             else
  329.             OPrint(
  330.                 "Postman collects the mail from the mailbox.\n");
  331.             fi;
  332.             while count ~= 0 do
  333.             count := count - 1;
  334.             letter := ltHere[count];
  335.             AddTail(ltMan, letter);
  336.             DelElement(ltHere, letter);
  337.             od;
  338.             if here = r_mailRoom and route ~= "" then
  339.             /* deliver the mail (plunk it down right here) */
  340.             ltMan := me@p_oLettersHere;
  341.             ltHere := here@p_oLettersHere;
  342.             count := Count(ltMan);
  343.             while count ~= 0 do
  344.                 count := count - 1;
  345.                 letter := ltMan[count];
  346.                 AddTail(ltHere, letter);
  347.                 DelElement(ltMan, letter);
  348.             od;
  349.             OPrint("Postman disappears into the private "
  350.                 "areas of the mailroom.\n");
  351.             ForEachAgent(r_mailRoom, UnShowIconOnce);
  352.             SetLocation(r_postmanHidden);
  353.             /* a two-step process to make sure that he has
  354.                collected and delivered all mail before he goes
  355.                idle */
  356.             if me@p_oPostManClearing then
  357.                 me@p_oPostManCleared := true;
  358.             else
  359.                 me@p_oPostManClearing := true;
  360.             fi;
  361.             After(300, postmanStep);
  362.             else
  363.             me@p_oPostManRoute := mailbox@p_oPostManRoute;
  364.             me@p_oPostManIndex := 0;
  365.             After(20, postmanStep);
  366.             fi;
  367.         fi;
  368.         fi;
  369.     else
  370.         ignore Parse(G, SubString(route, index, 1));
  371.         index := index + 1;
  372.         me@p_oPostManIndex := index;
  373.         /* Here() is AFTER the call to Parse! */
  374.         if Here() = r_mallEntrance then
  375.         ignore recorderErase();
  376.         fi;
  377.         After(20, postmanStep);
  378.     fi;
  379.     fi;
  380. corp;
  381.  
  382. define tp_mail proc postmanDesc()string:
  383.  
  384. "The postman, dressed in official postal service blue and carrying the "
  385. "standard satchel for letters, is not actually delivering mail. Rather, he is "
  386. "picking mail up at the various mailboxes and taking it in for delivery. " +
  387.     if Count(It()@p_oLettersHere) = 0 then
  388.     "The postman's satchel appears to be empty."
  389.     else
  390.     "The postman's satchel appears to contain some letters."
  391.     fi
  392. corp;
  393.  
  394. define tp_mail proc postmanHear(string what)void:
  395.     string word;
  396.  
  397.     word := SetSay(what);
  398.     if word ~= "" and word ~= "Packrat" then
  399.     if GetWord() == "Postman" then
  400.         OPrint("Postman mutters something about dogs and hailstones.\n");
  401.     fi;
  402.     fi;
  403. corp;
  404.  
  405. define tp_mail proc postmanPre()status:
  406.  
  407.     SPrint(TrueMe(), "Postman refuses the gift.\n");
  408.     fail
  409. corp;
  410.  
  411. define tp_mail proc postmanStart()void:
  412.     thing me;
  413.     int delay;
  414.  
  415.     me := Me();
  416.     delay := me@p_oPostManDelay;
  417.     me -- p_oPostManDelay;
  418.     After(delay, postmanStep);
  419. corp;
  420.  
  421. define tp_mail proc postmanCreate(int delay)void:
  422.     thing postman;
  423.  
  424.     postman := CreateThing(nil);
  425.     SetupMachine(postman);
  426.     postman@p_pStandard := true;
  427.     postman@p_oLettersHere := CreateThingList();
  428.     postman@p_pDescAction := postmanDesc;
  429.     postman@p_oPostManClearing := false;
  430.     postman@p_oPostManCleared := false;
  431.     postman@p_oPostManDelay := delay;
  432.     postman@p_pGivePre := postmanPre;
  433.     CreateMachine("Postman", postman, r_postmanHidden, postmanStart);
  434.     ignore SetMachineActive(postman, postmanStep);
  435.     ignore SetMachineSay(postman, postmanHear);
  436.     GNewIcon(postman, makePostmanIcon());
  437. corp;
  438.  
  439. postmanCreate(0).
  440. /* postmanCreate(300). */
  441. /* postmanCreate(600). */
  442. ignore DeleteSymbol(tp_mail, "postmanCreate").
  443.  
  444. define tp_mail proc mailMakeLetter(string s)void:
  445.     thing me, target, letter;
  446.     string myName;
  447.  
  448.     me := Me();
  449.     myName := FormatName(me@p_pName);
  450.     target := me@p_pLetterTarget;
  451.     me -- p_pLetterTarget;
  452.     letter := CreateThing(o_letter);
  453.     AddTail(me@p_pCarrying, letter);
  454.     letter@p_oName := FormatName(target@p_pName) + ";letter,for.letter";
  455.     letter@p_oReadString :=
  456.     "Date: " + Date() + "\nFrom: " + myName + "\n\n" + s;
  457.     letter@p_pLetterTarget := target;
  458.     letter@p_oLetterSender := me;
  459.     letter@p_oCarryer := me;
  460.     letter@p_oCreator := me;
  461.     SetThingStatus(letter, ts_public);
  462.     GiveThing(letter, SysAdmin);
  463.     if not me@p_pHidden and CanSee(Here(), me) then
  464.     OPrint(myName + " finishes writing.\n");
  465.     else
  466.     OPrint("The quiet scratching noise stops.\n");
  467.     fi;
  468.     Print("Letter finished. Now all you need to do is post it.\n");
  469. corp;
  470.  
  471. define tp_mail proc makeBulletin(string s)void:
  472.     thing me, bulletin;
  473.     string myName;
  474.  
  475.     me := Me();
  476.     myName := me@p_pName;
  477.     bulletin := CreateThing(o_bulletin);
  478.     AddTail(me@p_pCarrying, bulletin);
  479.     bulletin@p_oName := "bulletin,note";
  480.     bulletin@p_oReadString :=
  481.     "Date: " + Date() + "\nBy: " + myName + "\n\n" + s;
  482.     bulletin@p_oLetterSender := me;
  483.     bulletin@p_oCarryer := me;
  484.     bulletin@p_oCreator := me;
  485.     SetThingStatus(bulletin, ts_public);
  486.     GiveThing(bulletin, SysAdmin);
  487.     if not me@p_pHidden and CanSee(Here(), me) then
  488.     OPrint(myName + " finishes writing.\n");
  489.     else
  490.     OPrint("The quiet scratching noise stops.\n");
  491.     fi;
  492.     Print("Bulletin finished. Now all you need to do is post it.\n");
  493. corp;
  494.  
  495. define tp_mail proc writeNote(thing targetThing)bool:
  496.     thing me;
  497.  
  498.     me := Me();
  499.     if FindName(me@p_pCarrying, p_oName, "pad;writing") = fail then
  500.     Print("You have no pad to write on.\n");
  501.     false
  502.     elif FindName(me@p_pCarrying, p_oName, "pen;ballpoint") = fail then
  503.     Print("You have no ballpoint pen to write with.\n");
  504.     false
  505.     elif not CanSee(Here(), me) then
  506.     Print("You can't write in the dark.\n");
  507.     false
  508.     else
  509.     if targetThing ~= nil then
  510.         me@p_pLetterTarget := targetThing;
  511.         if GetDocument("mail> ", "Enter body of letter",
  512.                "", mailMakeLetter, false)
  513.         then
  514.         if not me@p_pHidden and CanSee(Here(), me) then
  515.             OPrint(FormatName(me@p_pName) + " starts writing.\n");
  516.         else
  517.             OPrint("You hear a quiet scratching noise start.\n");
  518.         fi;
  519.         true
  520.         else
  521.         false
  522.         fi
  523.     else
  524.         if GetDocument("bulletin> ", "Enter body of bulletin",
  525.                "", makeBulletin, false)
  526.         then
  527.         if not me@p_pHidden and CanSee(Here(), me) then
  528.             OPrint(FormatName(me@p_pName) + " starts writing.\n");
  529.         else
  530.             OPrint("You hear a quiet scratching noise start.\n");
  531.         fi;
  532.         true
  533.         else
  534.         false
  535.         fi
  536.     fi
  537.     fi
  538. corp;
  539.  
  540. define tp_mail proc mailTo(string who)bool:
  541.     character targetPlayer;
  542.     thing targetThing, me;
  543.  
  544.     me := Me();
  545.     if who == "me" then
  546.     who := me@p_pName;
  547.     fi;
  548.     targetPlayer := Character(who);
  549.     if targetPlayer = nil then
  550.     targetPlayer := Character(Capitalize(who));
  551.     fi;
  552.     if targetPlayer = nil then
  553.     targetThing := FindAgent(who);
  554.     if targetThing = nil then
  555.         Print("Character \"" + FormatName(who) +
  556.         "\" does not exist. Make sure you have the spelling and "
  557.         "capitalization right.\n");
  558.     else
  559.         /* must have been a machine in the same location! */
  560.         Print("Sorry, " + who + " hasn't registered for mail yet.\n");
  561.     fi;
  562.     false
  563.     else
  564.     targetThing := CharacterThing(targetPlayer);
  565.     if not targetThing@p_pMailRegistered then
  566.         Print("Sorry, " + who + " hasn't registered for mail yet.\n");
  567.         false
  568.     else
  569.         writeNote(targetThing)
  570.     fi
  571.     fi
  572. corp;
  573.  
  574. define tp_mail proc v_write()bool:
  575.     string error, help, word;
  576.  
  577.     error := "You must specify who you want to write a letter to.\n";
  578.     help :=
  579.         "Use 'post' to post a letter or bulletin, "
  580.         "'mail <who>' or 'write <who>' to write a letter, "
  581.         "and 'write bulletin' to write a bulletin.\n";
  582.     word := GetWord();
  583.     if word == "a" then
  584.     word := GetWord();
  585.     fi;
  586.     if word == "to" then
  587.     word := GetWord();
  588.     if word = "" then
  589.         Print(error);
  590.         false
  591.     else
  592.         mailTo(word)
  593.     fi
  594.     elif word == "letter" then
  595.     word := GetWord();
  596.     if word = "" then
  597.         if FindName(Me()@p_pCarrying, p_oName, "letter") ~= fail then
  598.         Print(help);
  599.         else
  600.         Print(error);
  601.         fi;
  602.         false
  603.     elif word == "to" then
  604.         mailTo(GetWord())
  605.     else
  606.         mailTo(word)
  607.     fi
  608.     elif word == "bulletin" then
  609.     word := GetWord();
  610.     if word = "" then
  611.         writeNote(nil)
  612.     elif word == "to" then
  613.         Print("You can't write bulletins to individuals. You can write "
  614.           "letters to people, or you can write public bulletins.\n");
  615.         false
  616.     else
  617.         Print("I don't understand what you want to write. ");
  618.         Print(help);
  619.         false
  620.     fi
  621.     elif Character(word) ~= nil then
  622.     mailTo(word)
  623.     elif word = "" then
  624.     Print(error);
  625.     false
  626.     else
  627.     Print("I don't understand who you want to write to. "
  628.           "Make sure you have the spelling and "
  629.           "capitalization of the name right. If you are trying to "
  630.           "write a bulletin, use 'write bulletin'.\n");
  631.     false
  632.     fi
  633. corp;
  634.  
  635. VerbTail(G, "write", v_write).
  636. Synonym(G, "write", "mail").
  637.  
  638. define tp_mail o_mail CreateThing(nil).
  639. SetupObject(o_mail, r_mailRoom, "mail,letters;my,new", "").
  640. o_mail@p_oInvisible := true.
  641. o_mail@p_oReadString :=
  642.     "Use 'get mail' or something similar to pick up your new mail first.".
  643. define tp_mail proc mailGet(thing letter)status:
  644.     list thing letters, carrying;
  645.     thing me;
  646.     int count, n;
  647.     bool gotOne;
  648.  
  649.     me := Me();
  650.     carrying := me@p_pCarrying;
  651.     letters := r_mailRoom@p_oLettersHere;
  652.     count := Count(letters);
  653.     gotOne := false;
  654.     n := 0;
  655.     while n ~= count do
  656.     letter := letters[n];
  657.     if letter@p_pLetterTarget = me then
  658.         Print("You have a " + FormatName(letter@p_oName) + ".\n");
  659.         DelElement(letters, letter);
  660.         count := count - 1;
  661.         AddTail(carrying, letter);
  662.         letter@p_oCarryer := me;
  663.         letter@p_oCreator := me;
  664.         gotOne := true;
  665.     else
  666.         n := n + 1;
  667.     fi;
  668.     od;
  669.     if gotOne then
  670.     if not me@p_pHidden then
  671.         OPrint(FormatName(me@p_pName) + " picks up some new mail.\n");
  672.     fi;
  673.     else
  674.     Print("You have no mail.\n");
  675.     if not me@p_pHidden then
  676.         OPrint(FormatName(me@p_pName) + " looks, but has no mail.\n");
  677.     fi;
  678.     fi;
  679.     succeed
  680. corp;
  681. o_mail@p_oGetChecker := mailGet.
  682.  
  683. define tp_mail proc doPostLetter(thing letter)bool:
  684.     thing me, sender, mailbox;
  685.     list thing lt;
  686.     status st;
  687.  
  688.     st := FindName(Here()@p_rContents, p_oName, "mailbox");
  689.     if st = fail then
  690.     Print("There is no mailbox here.\n");
  691.     false
  692.     else
  693.     mailbox := FindResult();
  694.     lt := mailbox@p_oLettersHere;
  695.     if Parent(mailbox) ~= o_mailbox or lt = nil then
  696.         Print("Sorry, the mailbox here isn't official.\n");
  697.         false
  698.     else
  699.         me := Me();
  700.         sender := letter@p_oLetterSender;
  701.         if sender ~= o_postalService then
  702.         letter@p_oName := FormatName(sender@p_pName) +
  703.             ";letter,from.letter";
  704.         fi;
  705.         AddTail(lt, letter);
  706.         letter -- p_oCarryer;
  707.         DelElement(me@p_pCarrying, letter);
  708.         /* force Postman to deliver it before idling */
  709.         r_mailRoom@p_rNewLetter := true;
  710.         Print("Letter posted.\n");
  711.         if not me@p_pHidden then
  712.         OPrint(FormatName(me@p_pName) +
  713.             " posts a letter.\n");
  714.         fi;
  715.         true
  716.     fi
  717.     fi
  718. corp;
  719.  
  720. define tp_mail proc doPostBulletin(thing bulletin)bool:
  721.     thing board, oldNote;
  722.     list thing lt;
  723.     status st;
  724.     int n;
  725.  
  726.     st := FindName(Here()@p_rContents, p_oName, "board;bulletin");
  727.     if st = fail then
  728.     Print("There is no bulletin board here.\n");
  729.     false
  730.     else
  731.     board := FindResult();
  732.     lt := board@p_oContents;
  733.     if Parent(board) ~= o_bulletinBoard or lt = nil then
  734.         Print("Sorry, the bulletin board here isn't official.\n");
  735.         false
  736.     else
  737.         actualPostBulletin(bulletin, board);
  738.         true
  739.     fi
  740.     fi
  741. corp;
  742.  
  743. define tp_mail proc v_post(string what)bool:
  744.     thing me, letter;
  745.     string name;
  746.     status st;
  747.  
  748.     if what = "" then
  749.     Print("You must specify what you want to post.\n");
  750.     false
  751.     else
  752.     me := Me();
  753.     name := FormatName(what);
  754.     st := FindName(me@p_pCarrying, p_oName, what);
  755.     if st = fail then
  756.         Print(AAn("You are not carrying", name) + ".\n");
  757.         false
  758.     elif st = continue then
  759.         Print(name + " is ambiguous here.\n");
  760.         false
  761.     else
  762.         letter := FindResult();
  763.         if Parent(letter) = o_letter then
  764.         if letter@p_oCreator ~= me and MeCharacter() ~= SysAdmin then
  765.             Print("That's not your letter.\n");
  766.             false
  767.         else
  768.             doPostLetter(letter)
  769.         fi
  770.         elif Parent(letter) = o_bulletin then
  771.         if letter@p_oCreator ~= me and MeCharacter() ~= SysAdmin then
  772.             Print("That's not your bulletin.\n");
  773.             false
  774.         else
  775.             doPostBulletin(letter)
  776.         fi
  777.         else
  778.         Print("The " + name + " is not something you can post.\n");
  779.         false
  780.         fi
  781.     fi
  782.     fi
  783. corp;
  784.  
  785. Verb1(G, "post", 0, v_post).
  786.  
  787. define tp_mail proc mailRoomDrop(thing th)status:
  788.  
  789.     if Parent(th) = o_letter then
  790.     Print("The letter somehow wafts its way into the mailbox.\n");
  791.     if Me()@p_pHidden then
  792.         OPrint("A letter appears and wafts into the mailbox.\n");
  793.     else
  794.         OPrint(Me()@p_pName +
  795.         " drops a letter, which wafts into the mailbox.\n");
  796.     fi;
  797.     if doPostLetter(th) then
  798.         succeed
  799.     else
  800.         continue
  801.     fi
  802.     else
  803.     continue
  804.     fi
  805. corp;
  806. AddRoomDropChecker(r_mailRoom, mailRoomDrop, false).
  807.  
  808. define tp_mail proc makeMailBox(thing room; string route)void:
  809.     thing mailbox;
  810.  
  811.     mailbox := CreateThing(o_mailbox);
  812.     SetThingStatus(mailbox, ts_readonly);
  813.     AddTail(room@p_rContents, mailbox);
  814.     mailbox@p_oPostManRoute := route;
  815.     mailbox@p_oLettersHere := CreateThingList();
  816. corp;
  817.  
  818. makeMailBox(r_mailRoom, "seene").
  819. makeMailBox(r_ne3, "ssseees").
  820. makeMailBox(r_es4, "wwwwssw").
  821. makeMailBox(r_sw3, "nnnwwwn").
  822. makeMailBox(r_wn3, "eeennwwn").
  823.  
  824. define t_util proc MakeBulletinBoard(thing room)void:
  825.     thing board;
  826.  
  827.     board := CreateThing(o_bulletinBoard);
  828.     board@p_oBulletinNumber := 1;
  829.     board@p_oContents := CreateThingList();
  830.     SetThingStatus(board, ts_readonly);
  831.     AddTail(room@p_rContents, board);
  832. corp;
  833.  
  834. MakeBulletinBoard(r_wn2).
  835.  
  836. CharacterThing(SysAdmin)@p_pMailRegistered := true.
  837.  
  838. unuse tp_mail
  839. unuse t_streets
  840.